package kline

import (
	"global/core"
	"global/model"
	"github.com/ngaut/log"
	"sync"
	"global/libs/structs"
	"strings"
)

type KlineManager struct {
	Ctx 		*core.Context
	Coins 		[]*model.Coin

	handlers  	map[string]*KlineHandleCoin



	mux 		sync.Mutex
	wg 			sync.WaitGroup
}

func NewKlineManager(ctx *core.Context) *KlineManager {
	manager := &KlineManager{
		Ctx: 			ctx,
		Coins: 			make([]*model.Coin, 0),
		handlers: 		make(map[string]*KlineHandleCoin),
	}
	manager.Init()
	return manager
}

// 初始化
func (m *KlineManager) Init() {
	m.loadCoins()
}

func (m *KlineManager) getDataFromQueue() {
	go func() {
		conn := m.Ctx.GetBaseRedis().Get()
		defer conn.Close()
		for {
			res, err := core.GetKlineDataFromQueue(conn)
			if err != nil {
				log.Errorf("Error: %s", err)
				continue
			}
			m.dispatch(res)
		}
	}()
}

// 分发
func (m *KlineManager) dispatch(p *structs.CoinKlineQueue) {
	m.mux.Lock()
	defer m.mux.Unlock()
	if v, ok := m.handlers[p.CoinName]; ok {
		v.data <- p
	} else {
		h := m.newHandler(p.CoinName)
		h.data <- p
	}
}

// 开启服务
func (m *KlineManager) Serv() {
	m.wg.Add(len(m.Coins))
	for _, v := range m.Coins {
		go func(coin *model.Coin) {
			defer m.wg.Done()
			m.newHandler(v.Symbol)
		}(v)
	}
	m.wg.Wait()
	m.getDataFromQueue()
}

func (m *KlineManager) newHandler(s string) *KlineHandleCoin {
	s = strings.ToLower(s)
	h := NewKlineHandleCoin(m.Ctx, s)
	h.Start()

	m.mux.Lock()
	m.handlers[s] = h
	m.mux.Unlock()
	return h
}

// 加载币种
func (m *KlineManager) loadCoins() {
	coins, err := model.CoinModel.FindAll()
	if err != nil {
		log.Fatalf("Error: get coin failed, %s", err)
	}

	if len(coins) == 0 {
		log.Fatalf("Error: no coin returned")
	}

	m.mux.Lock()
	m.Coins = coins
	m.mux.Unlock()
}